﻿//========================================================= 
/**@file HidComIC_DevUpdater.h
 * @brief 
 * 
 * @date 2016-05-07   16:15:58
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_HIDCOMIC_DEVUPDATER_H_
#define _LIBZHOUYB_HIDCOMIC_DEVUPDATER_H_
//--------------------------------------------------------- 
#include "COM_IC_DevUpdater.h"
#include "../../test_frame/linker/WinHidTestLinker.h"
using zhou_yb::application::test::WinHidTestLinker;
//--------------------------------------------------------- 
namespace zhou_yb {
namespace application {
namespace updater {
//--------------------------------------------------------- 
/// 通过COM的协议检测HID升级设备是否存在
class HidComUpdateModeTestLinker : public TestLinker<FixedHidTestDevice>
{
protected:
    WinHidTestLinker _hidLinker;
public:
    /**
     * @brief 扫描HID设备,并发送升级切换指令
     * 
     * @param [in] dev 需要操作的设备
     * @param [in] arg 参数列表
     * - 参数
     *  - Updater : string 升级模式参数
     *   - Name : string BOOT名称
     *   - TransmitMode : string 端点传输方式
     *  .
     *  - Reader : string 正常模式名称
     *   - Name : string 设备名称
     *   - TransmitMode : string 端点传输方式
     *  .
     * .
     * @param [in] printer 文本输出器
     */
    virtual bool Link(FixedHidTestDevice& dev, IStringArguments& arg, TextPrinter& printer)
    {
        string reader = "";
        string upgrade = "";

        ArgParser parser;
        StringArguments cfgReader;
        StringArguments cfgUpdater;
        parser.Parse(arg["Updater"].Value.c_str(), cfgUpdater);
        upgrade = cfgUpdater["Name"].To<string>();

        parser.Parse(arg["Reader"].Value.c_str(), cfgReader);
        reader = cfgReader["Name"].To<string>();

        printer.Print(TextPrinter::TextLogger)
            << "Updater:<" << upgrade << ">,Reader:<" << reader << ">" << off;

        list_t<HidDevice::device_info> devlist;
        list_t<HidDevice::device_info>::iterator itr;
        dev.Base().EnumDevice(devlist);

        for(itr = devlist.begin();itr != devlist.end(); ++itr)
        {
            if(StringConvert::Contains(ByteArray(itr->Name.c_str(), itr->Name.length()),
                ByteArray(upgrade.c_str(), upgrade.length()), true))
            {
                if(!_hidLinker.Link(dev, cfgUpdater, printer))
                {
                    printer.TextPrint(TextPrinter::TextLogger, "连接升级设备失败");
                    return false;
                }
                if(!ComUpdateModeSwitcher::IsUpgradeMode(dev))
                {
                    printer.TextPrint(TextPrinter::TextWarning, "检测设备升级模式失败");
                    break;
                }
                printer.TextPrint(TextPrinter::TextLogger, "设备已经为升级模式");
                return true;
            }
        }
        printer.TextPrint(TextPrinter::TextLogger, "连接设备");
        if(!_hidLinker.Link(dev, cfgReader, printer))
            return false;

        printer.TextPrint(TextPrinter::TextLogger, "切换设备为升级模式");

        // 发送升级指令后等待设备切换模式
        ComUpdateModeSwitcher::ToUpgradeMode(dev);
        dev.Base().Close();
        return false;
    }
    /// 关闭串口
    virtual bool UnLink(FixedHidTestDevice& dev, TextPrinter&)
    {
        dev.Base().Close();
        return true;
    }
};
//--------------------------------------------------------- 
/// 连接升级模式下的设备
class HidComUpdateTestLinker : public WinHidTestLinker
{
public:
    virtual bool Link(FixedHidTestDevice& dev, IStringArguments& arg, TextPrinter& printer)
    {
        if(WinHidTestLinker::Link(dev, arg, printer))
        {
            if(ComUpdateModeSwitcher::IsUpgradeMode(dev))
                return true;
            WinHidTestLinker::UnLink(dev, printer);
        }
        return false;
    }
};
//--------------------------------------------------------- 
/// 将数据组成一个包直接以串口流式数据的方式发送
class HidComUpdaterTestCase : public ITestCase<IInteractiveTrans>
{
protected:
    /// 已升级的文件行数
    size_t _updateCount;
    /// 发送N条后接收状态码
    size_t _swCount;
    /// 发送的升级数据
    ByteBuilder _updateBin;
public:
    HidComUpdaterTestCase(size_t swCount = 1) : _swCount(swCount), _updateCount(0) {}
    /// 升级行
    virtual bool Test(Ref<IInteractiveTrans>& testObj, const ByteArray& testArg, TextPrinter&)
    {
        /* 开始升级数据 */
        byte len = _itobyte(testArg.GetLength());
        _updateBin.Clear();
        _updateBin += len;
        _updateBin += testArg;
        bool bUpdate = testObj->Write(_updateBin);
        if(bUpdate)
        {
            ++_updateCount;
            // 连续发送N条或最后一条才判断状态码 
            if((_updateCount >= _swCount))
            {
                _updateCount = 0;
                return ComUpdateModeSwitcher::WaitSW(testObj);
            }
            return true;
        }
        return false;
    }
};
//--------------------------------------------------------- 
} // namespace updater
} // namespace application
} // namespace zhou_yb
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_HIDCOMIC_DEVUPDATER_H_
//========================================================= 
